﻿<Serializable()> _
Public Class Day




    Private _Label As String
    Public Property Label() As String
        Get
            Return _Label
        End Get
        Set(ByVal value As String)
            _Label = value
        End Set
    End Property
    Private _Locations As New List(Of String)
    <Xml.Serialization.XmlArray("Locations"), _
    Xml.Serialization.XmlArrayItem("Location", GetType(String))> _
    Public Property Locations() As String()
        Get
            Return _Locations.ToArray

        End Get
        Set(ByVal value As String())
            _Locations = New List(Of String)
            _Locations.AddRange(value)
        End Set
    End Property

    Private _StartTimes As New List(Of Date)
    <Xml.Serialization.XmlArray("StartTimes"), _
    Xml.Serialization.XmlArrayItem("Start", GetType(DateTime))> _
    Public Property StartTimes() As Date()
        Get
            Return _StartTimes.ToArray

        End Get
        Set(ByVal value As Date())
            _StartTimes = New List(Of Date)
            _StartTimes.AddRange(value)
        End Set
    End Property
    <Xml.Serialization.XmlArray("ScheduleTypes"), Xml.Serialization.XmlArrayItem("ScheduleType", GetType(String))>
    Property ScheduleEmployeeTypes As New List(Of String)

    Private _EndTimes As New List(Of Date)
    <Xml.Serialization.XmlArray("EndTimes"), _
    Xml.Serialization.XmlArrayItem("End", GetType(DateTime))> _
    Public Property EndTimes() As Date()
        Get
            Return _EndTimes.ToArray
        End Get
        Set(ByVal value As Date())
            _EndTimes = New List(Of Date)
            _EndTimes.AddRange(value)

        End Set
    End Property


    <Xml.Serialization.XmlArray("Exceptions"), _
    Xml.Serialization.XmlArrayItem("Exception", GetType(TimeRangeException))> _
    Private _TimeExceptions As New List(Of TimeRangeException)
    Public Property TimeExceptions() As List(Of TimeRangeException)
        Get
            Return _TimeExceptions
        End Get
        Set(ByVal value As List(Of TimeRangeException))
            _TimeExceptions = value
        End Set
    End Property
    Public Function AddTimeRange(ByVal StartTime As Date, ByVal EndTime As Date, ScheduleType As String, ByVal Location As String) As TimeSpan
        If StartTime > EndTime Then Return TimeSpan.Zero
        _StartTimes.Add(StartTime)
        _EndTimes.Add(EndTime)
        _Locations.Add(Location)
        ScheduleEmployeeTypes.Add(ScheduleType)
        Return EndTime.Subtract(StartTime)


    End Function
    'Public Sub SortTimeRanges()
    '    'todo write code to sort the timeranges by start date

    'End Sub
    Public Sub Clear(Optional ByVal IncludeExceptions As Boolean = True)
        If IncludeExceptions Then Me.TimeExceptions.Clear()
        Me._StartTimes.Clear()
        Me._EndTimes.Clear()
        ScheduleEmployeeTypes.Clear()
        _Locations.Clear()

    End Sub
    Public Function RemoveTimeRange(ByVal index As Integer) As Boolean
        If index >= StartTimes.Count Then Return False
        _StartTimes.RemoveAt(index)
        _EndTimes.RemoveAt(index)
        ScheduleEmployeeTypes.RemoveAt(index)
        _Locations.RemoveAt(index)
        Dim del = (From ex In TimeExceptions Where ex.TimeRange = index).ToList




        TimeExceptions.RemoveAll(Function(ex)
                                     Return del.Contains(ex)
                                 End Function)

        Return True
    End Function

    Public Sub New()

    End Sub
    Public Sub New(ByVal Label As String)
        Me.Label = Label

    End Sub


    Public Overloads Function ToString(ByVal Format As String) As String

        If String.IsNullOrEmpty(Format) Then Return Me.ToString
        Select Case Format.ToUpper
            Case "R"

        End Select
        Return ToString()
    End Function
    Public Function GetDayTimeRange(index As Integer) As Tuple(Of TimeSpan, TimeSpan)
        Dim result As New Tuple(Of TimeSpan, TimeSpan)(TimeSpan.Zero, TimeSpan.Zero)

        If index < 0 OrElse index >= Me.StartTimes.Count Then Return result



        Dim st As Date = Me.StartTimes(index)
        Dim en As Date = Me.EndTimes(index)

        result = New Tuple(Of TimeSpan, TimeSpan)(st.TimeOfDay, en.TimeOfDay)

        Return result
    End Function
    ''' <summary>
    ''' Splits a time range so that the original time range runs from the start through SplitDate.  
    ''' Then creates a new time range that will start on the next day after SplitDate and run to the original end date.
    ''' </summary>en
    ''' <param name="timeRange">The index to use when getting the time range to modify.</param>
    ''' <param name="SplitDate">The date to stop at and split on.</param>
    ''' <remarks></remarks>
    Public Sub SplitSchedule(timeRange As Integer, SplitDate As Date)
        If timeRange >= Me.StartTimes.Count Then Throw New ArgumentOutOfRangeException("timeRange")
        Dim st As Date = Me.StartTimes(timeRange), en As Date = Me.EndTimes(timeRange)
        Dim original As New DevExpress.XtraScheduler.TimeInterval(st, en)
        If Not original.Contains(SplitDate) Then Throw New ArgumentOutOfRangeException("SplitDate", "Split date must be in the time range selected.")
        Dim split As New DevExpress.XtraScheduler.TimeInterval(New Date(SplitDate.Year, SplitDate.Month, SplitDate.AddDays(1).Day), en.Date.Date.AddHours(23).AddMinutes(59))


        Me._EndTimes(timeRange) = New Date(SplitDate.Year, SplitDate.Month, SplitDate.Day, en.Hour, en.Minute, en.Second)
        Dim newTime As Integer = Me.StartTimes.Count
        Me.AddTimeRange(New Date(split.Start.Year, split.Start.Month, split.Start.Day, st.Hour, st.Minute, st.Second), en, Me.ScheduleEmployeeTypes(timeRange), Me.Locations(timeRange))
        For Each te In From t In Me.TimeExceptions Where t.TimeRange = timeRange AndAlso split.Contains(t.Day)
            te.TimeRange = newTime
        Next


    End Sub
    Private Function GetRangeString() As String
        If StartTimes.Length = 0 Then Return ""
        Dim first, last As Date
        first = StartTimes(0)
        last = EndTimes(0)

        For Each tm As Date In StartTimes
            If first > tm Then first = tm

        Next
        For Each tm As Date In EndTimes
            If last < tm Then last = tm

        Next
        Return first.ToShortTimeString & "-" & last.ToShortTimeString

    End Function
    Public Overrides Function ToString() As String
        Return Me.Label

    End Function
End Class
<Xml.Serialization.XmlRoot("Holidays")>
<Serializable()>
Public Class HolidayInfoList
    Inherits List(Of HolidayInfo)

End Class
Public Class HolidayInfo
    Implements IComparable(Of HolidayInfo)


    Private _IsGeneralHoliday As Boolean
    ''' <summary>
    ''' Determines if this holiday is a holiday that applies to every employee.
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property IsGeneralHoliday() As Boolean
        Get
            Return _IsGeneralHoliday
        End Get
        Set(ByVal value As Boolean)
            _IsGeneralHoliday = value
        End Set
    End Property



    Private _Caption As String
    Public Property Caption() As String
        Get
            Return _Caption
        End Get
        Set(ByVal value As String)
            _Caption = value
        End Set
    End Property

    Private _day As Date
    Public Property Day() As Date
        Get
            Return _day
        End Get
        Set(ByVal value As Date)
            _day = value
        End Set
    End Property

    Private _EndDay As DateTime?

    Public Property EndDate() As DateTime?
        Get
            Return _EndDay
        End Get
        Set(ByVal value As DateTime?)
            If value.HasValue Then
                If Day > value.Value Then value = Nothing

            End If
            _EndDay = value
        End Set
    End Property



    Public Sub New()
        Day = Now

    End Sub
    Public Sub New(ByVal Day As Date, ByVal Caption As String, ByVal GeneralHoliday As Boolean)
        Me.Day = Day
        Me.Caption = Caption
        IsGeneralHoliday = GeneralHoliday
    End Sub
    Public Sub New(ByVal Day As Date, ByVal EndDate As DateTime?, ByVal Caption As String, ByVal GeneralHoliday As Boolean)
        MyClass.New(Day, Caption, GeneralHoliday)
        Me.EndDate = EndDate
    End Sub
    Public Overrides Function ToString() As String
        If Me.EndDate.HasValue Then
            Return Me.Caption & "[" & Me.Day.Date.ToShortDateString & "] - " & Me.EndDate.Value.ToShortDateString
        Else
            Return Me.Caption & "[" & Me.Day.Date.ToShortDateString & "]"
        End If


    End Function

    Public Function CompareTo(ByVal other As HolidayInfo) As Integer Implements System.IComparable(Of HolidayInfo).CompareTo
        If Me.IsGeneralHoliday = other.IsGeneralHoliday Then
            Return Me.Day.CompareTo(other.Day)
        Else
            If Me.IsGeneralHoliday Then
                Return 1
            Else
                Return -1

            End If

        End If
    End Function
End Class
Public Enum ExceptionTypes
    Replace = 0
    Add
    Delete
End Enum
Public Class TimeRangeException
    Implements IComparable(Of TimeRangeException)

    Property Location As String
    Private _ExceptionType As ExceptionTypes = ExceptionTypes.Replace
    <System.ComponentModel.DefaultValue(0)> _
    Public Property ExceptionType() As ExceptionTypes
        Get
            Return _ExceptionType
        End Get
        Set(ByVal value As ExceptionTypes)
            _ExceptionType = value
        End Set
    End Property
    Private _TimeRange As Integer
    Public Property TimeRange() As Integer
        Get
            Return _TimeRange
        End Get
        Set(ByVal value As Integer)
            _TimeRange = value
        End Set
    End Property


    Private _day As Date
    Public Property Day() As Date
        Get
            Return _day
        End Get
        Set(ByVal value As Date)
            _day = value

            _StartTime = New Date(Day.Year, Day.Month, Day.Day, _StartTime.Hour, _StartTime.Minute, 0)
            _EndTime = New Date(Day.Year, Day.Month, Day.Day, _EndTime.Hour, _EndTime.Minute, 0)
        End Set
    End Property

    Private _StartTime As Date
    Public Property StartTime() As Date
        Get
            Return _StartTime
        End Get
        Set(ByVal value As Date)
            _StartTime = value
            _StartTime = New Date(Day.Year, Day.Month, Day.Day, _StartTime.Hour, _StartTime.Minute, 0)
        End Set
    End Property

    Private _EndTime As Date
    Public Property EndTime() As Date
        Get
            Return _EndTime
        End Get
        Set(ByVal value As Date)
            _EndTime = value
            _StartTime = New Date(Day.Year, Day.Month, Day.Day, _StartTime.Hour, _StartTime.Minute, 0)
        End Set
    End Property
    Property ScheduleType As String
    Public Sub New()

    End Sub
    Public Sub New(ByVal Day As Date, ByVal startTime As Date, ByVal endTime As Date, ByVal TimeRange As Integer, ScheduleType As String, Location As String, Optional ByVal exType As ExceptionTypes = ExceptionTypes.Replace)
        Me.Day = Day
        Me.StartTime = startTime
        Me.EndTime = endTime
        Me.TimeRange = TimeRange
        _ExceptionType = exType
        Me.ScheduleType = ScheduleType
        Me.Location = Location
    End Sub

    Public Overrides Function ToString() As String
        Dim sb As New System.Text.StringBuilder
        If Me.ExceptionType = ExceptionTypes.Replace Then
            sb.Append("-")
        ElseIf Me.ExceptionType = ExceptionTypes.Delete Then
            sb.Append("X")

        Else
            sb.Append("+")
        End If
        sb.AppendFormat("{0} {1}-{2}", Day.ToShortDateString, StartTime.ToShortTimeString, EndTime.ToShortTimeString)

        Return sb.ToString

    End Function
    Public Overloads Function ToString(ByVal Format As String) As String
        If String.IsNullOrEmpty(Format) Then Return Me.ToString


        Select Case Format.ToLower
            Case "m"
                Dim sb As New System.Text.StringBuilder
                Return ""
            Case Else
                Return Me.ToString

        End Select
    End Function

    Public Function CompareTo(ByVal other As TimeRangeException) As Integer Implements System.IComparable(Of TimeRangeException).CompareTo
        If Day.Date = other.Day.Date Then
            Return StartTime.CompareTo(other.StartTime)
        Else
            Return Day.Date.CompareTo(other.Day.Date)

        End If
    End Function
End Class